//--------------------------------------------------------------------------
// 
//  Copyright (c) Chili Software.  All rights reserved. 
// 
//  File: FieldMetaInfo.cs
//
//  Description: Holds the runtime information on a mapped field.
// 
//--------------------------------------------------------------------------

using System;
using System.Reflection;

namespace Chili.Opf3.Mapping
{
	/// <summary>
	/// Class represents a meta element that is used to create the mapping between the persistent object and
	/// the field in the table.
	/// </summary>
	/// <remarks>
	/// This class represents a meta element that is used to create the mapping between a field
	/// of the persistent object and a field in the storage table.
	/// </remarks>
	internal sealed class FieldMetaInfo : MetaInfo
	{
		private FieldInfo _fieldInfo;

		/// <summary>
		/// Creates a new instance of the <see cref="FieldMetaInfo">FieldMetaInfo Class</see>.
		/// </summary>
		/// <param name="fieldInfo">The FieldInfo object that represents the field in the persistent object's type.</param>
		/// <param name="memberType">The type of the MemberInfo object.</param>
		/// <param name="attribute">The <see cref="FieldAttribute">FieldAttribute</see> that contains the mapping information.</param>
		public FieldMetaInfo(FieldInfo fieldInfo, Type memberType, FieldAttribute attribute)
			: base(memberType, fieldInfo, attribute)
		{
			if (fieldInfo == null)
				throw new ArgumentNullException("fieldInfo");
			_fieldInfo = fieldInfo;
		}

		/// <summary>
		/// Returns the name of the element of the persistent object type that is mapped to the field in the storage.
		/// </summary>
		public override string Name
		{
			get { return _fieldInfo.Name; }
		}

		/// <summary>
		/// Returns the value of the element of the persistent object type that is mapped to a field in the storage.
		/// </summary>
		/// <param name="obj">The persistent object that's value is returned.</param>
		/// <returns>Value of the persistent object's type element that is mapped to a field in the storage.</returns>
		public override object GetValue(object obj)
		{
			object val = _fieldInfo.GetValue(obj);

			if (IsUserDefinedType && val != null)
				val = ((IUserDefinedType)val).ToSimpleDataType();

			return val;
		}

		/// <summary>
		/// Sets new value for the element of the persistent object type that is mapped to the storage.
		/// </summary>
		/// <param name="obj">The persistent object that's member's value is updated.</param>
		/// <param name="value">The new value.</param>
		public override void SetValue(object obj, object value)
		{
			if (IsUserDefinedType)
				((IUserDefinedType)_fieldInfo.GetValue(obj)).FromSimpleDataType(value);
			else
				_fieldInfo.SetValue(obj, value, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, null);
		}
	}
}
